﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;

namespace Archiver
{
    class Binary
    {
        /// <summary>
        /// Функция представляет длинное целое в двоичной системе 
        /// </summary>
        /// <param name="a">Целое число в десятичной системе</param>
        /// <returns>Двочное предствление числа а</returns>
        
        public static List<bool> ConvertStrToBitArray(string s)
        {
            var res = new List<bool>();
            for (var i = 0; i < s.Length; i++)
                res.Add(s[i] != '0');
            return res;
        }
        
        public static string ConvertIntToBin(BigInteger a)
        {
            var res = "";
            var c = a;
            BigInteger ost; 
            do
            {
                c = BigInteger.DivRem(c, 2, out ost);
                res += ost;
            }
            while (c > 1);
            if (c != 0)
                res += c;

            var res1 = "";
            for (var i = res.Length - 1; i >= 0; i--)
                res1 += res[i];
            return res1;
        }
        
        
        public static string ConvertIntToBin (int a)
        {
            var res = "";
            var c = a;
            var ost = 0; 
            
            do
            {
                ost = c % 2;
                c = c/2;
                res += ost; 
            }
            while(c>1);
            if (c!=0)
                res += c;
            
            var res1 = ""; 
            for (var i=res.Length-1; i>=0; i--)
                res1 += res[i];
            return res1; 
        }

        public static string ConvertIntToBin (int a, int len)
        {
            var res = ConvertIntToBin(a); 
                while (res.Length<len)
                    res = "0" + res;
            return res; 
        }

        public static string ConvertIntToBin (byte[] a)
        {
            var res = a.Aggregate("", (current, t) => current + ConvertIntToBin(t));
            return res;
        }

        public static string ConvertIntToBin(string a)
        {
            return ConvertIntToBin(int.Parse(a));
        }


        /// <summary>
        /// Предствляет двоичное число в десятичное
        /// </summary>
        /// <param name="a">Число в двоичной системе</param>
        /// <returns>Длинное целое</returns>
        public static BigInteger ConvertBinToInt(string a)
        {
            var aTrim = a.TrimStart('0');
            if (aTrim == "") aTrim = "0"; 
            var d = "";

            for (var i=aTrim.Length-1; i>=0; i--)
            {
                d += aTrim[i];
            }

            var res = new BigInteger(0);
            for (var i = 0; i < d.Length; i++)
                res += Convert.ToInt32(d.Substring(i,1))*BigInteger.Pow(2, i);

            return res;
        }

        public static byte ConvertBinToByte(List<bool> a)
        {
            if (a.Count == 0)
                return 0;
            
            var aTrim = TrimStart(a);
          
            byte res = 0;
            for (var i = aTrim.Count - 1; i >= 0; i--)
                if (aTrim[i])
                    res += Convert.ToByte(Math.Pow(2, aTrim.Count - i - 1));
            return res;
        }

        public static byte ConvertBinToByte(string a)
        {
            var aTrim = a.TrimStart('0');
            if (aTrim.Length == 0)
                aTrim = "0";

            byte res = 0;
            for (var i = aTrim.Length - 1; i >= 0; i--)
                if (aTrim[i] == '1') 
                    res += Convert.ToByte(Math.Pow(2, aTrim.Length- i - 1));
            return res;
        }

        public static bool[] SubArr(bool[] bits, int i)
        {
            var res = new bool[bits.Length - i];
            for (var j = i; j < bits.Length-i; j++)
                res[j] = bits[j];
            return res;
        }

        public static bool[] Concat(bool[] subArr, bool b)
        {
            var res = new bool[subArr.Length + 1]; 
            for (var i=0; i<res.Length-1;i++)
            {
                res[i] = subArr[i];
            }
            res[res.Length - 1] = b;
            return res;
        }

        public static bool Compare(bool[] value, bool[] bools)
        {
            if (value.Length != bools.Length)
                return false;
            return !value.Where((t, i) => t != bools[i]).Any();
        }

        public static List<bool> TrimStart(List<bool> value)
        {

            var t = new List<bool>(value);
            while (!t[0] && t.Count>1 )
                t.RemoveAt(0);
            return t;
        }

        public static string BitsArryToStr(List<bool> bools)
        {
            var res = bools.Aggregate("", (current, t) => current + (t ? '1' : '0'));
            return res;
        }
    }
}
